Drools Tutorial
================================

Bindings
------------

* Fact binding

Binding facts in the rule condition to the rule actions.

We want to update the account balance for each CashFlow. We first put the CashFlow and select all CashFlow of type CREDIT. To do so, we add a constraint on the "type" attribute of java class CashFlow.
- Add constants to CashFlow:
public static int CREDIT = 1;
public static int DEBIT = 2;

- Comment all rules in lesson1.drl

- Create a new file lesson2.drl with the following rule:

rule "Credit rule"

    when
        $cash :CashFlow(type == CashFlow.CREDIT )
        $acc : Account(  )
    then
        $acc.setBalance($acc.getBalance()+$cash.getAmount());
        System.out.println("Account no "+$acc.getAccountNo()+ 
        " has now a balance of "+$acc.getBalance());
end



- Create a test class with the following code:
            Account a = new Account();
            a.setAccountNo(1);
            a.setBalance(0);
            kSession.insert(a);
            
            CashFlow cash1 = new CashFlow();
            cash1.setAccountNo(1);
            cash1.setAmount(1000);
            cash1.setType(CashFlow.CREDIT);
            kSession.insert(cash1);
            
            CashFlow cash2 = new CashFlow();
            cash2.setAccountNo(2);
            cash2.setAmount(500);
            cash2.setType(CashFlow.CREDIT);
            kSession.insert(cash2);
            
            CashFlow cash3 = new CashFlow();
            cash3.setAccountNo(1);
            cash3.setAmount(500);
            cash3.setType(CashFlow.DEBIT);
            kSession.insert(cash3);
                        
            kSession.fireAllRules();
            System.out.println("Balance of account n. "
            +a.getAccountNo()+": "+a.getBalance()); //1000,0
            System.out.println("Close...");


- There are 2 problems:
1. Debit rule is missing to update the balance with the debit
2. cash2 is applied to accountNo 1, despite "cash2.setAccountNo(2)"

- Problem 1 is solved as follows:
rule "Debit rule"

    when
        $cash :CashFlow(type == CashFlow.DEBIT )
        $acc : Account(  )
    then
        $acc.setBalance($acc.getBalance()-$cash.getAmount());
        System.out.println("Account no "+$acc.getAccountNo()+ " has now a balance of "+$acc.getBalance());

end


- Problem 2 requires:

* Attribute binding

We want to link facts each other using their attributes.

- New rule:
rule "Credit rule"

    when
        $cash : CashFlow( $no : accountNo ,type == CashFlow.CREDIT )
        $acc : Account(accountNo ==$no  )
    then
		$acc.setBalance($acc.getBalance()+$cash.getAmount());
        System.out.println("Account no "+$acc.getAccountNo()+ " has now a balance of "+$acc.getBalance());

end



* Compute the balance

- New rules:
rule "Credit rule"

    when
        $cash : CashFlow( $aDate : mvtDate, $no : accountNo ,type == CashFlow.CREDIT )
        $acc : Account(accountNo ==$no  )
        $period : AccountingPeriod(  startDate <= $aDate && endDate >= $aDate)
    then
		$acc.setBalance($acc.getBalance()+$cash.getAmount());
        System.out.println("Account no "+$acc.getAccountNo()+ " has now a balance of "+$acc.getBalance());

end

rule "Debit rule"

    when
        $cash :CashFlow( $aDate : mvtDate, $no : accountNo ,type == CashFlow.DEBIT )
        $acc : Account(accountNo ==$no  )
        $period : AccountingPeriod(  startDate <= $aDate && endDate >= $aDate)
    then
        $acc.setBalance($acc.getBalance()-$cash.getAmount());
        System.out.println("Account no "+$acc.getAccountNo()+ " has now a balance of "+$acc.getBalance());

end


We also add a constraint so that the mvtDate of the CashFlow is between the startDate and endDate of the AccountinPeriod.


- Create a test class with the following code:

            Account a = new Account();
            a.setAccountNo(1);
            a.setBalance(0);
            kSession.insert(a);
            
            CashFlow cash1 = new CashFlow();
            cash1.setAccountNo(1);
            cash1.setAmount(1000);
            cash1.setMvtDate(new SimpleDateFormat("yyyy-MM-dd").parse("2016-01-15"));
            cash1.setType(CashFlow.CREDIT);
            kSession.insert(cash1);
            
            CashFlow cash2 = new CashFlow();
            cash2.setAccountNo(1);
            cash2.setAmount(500);
            cash2.setMvtDate(new SimpleDateFormat("yyyy-MM-dd").parse("2016-02-15"));
            cash2.setType(CashFlow.DEBIT);
            kSession.insert(cash2);
            
            CashFlow cash3 = new CashFlow();
            cash3.setAccountNo(1);
            cash3.setAmount(1000);
            cash3.setMvtDate(new SimpleDateFormat("yyyy-MM-dd").parse("2016-04-15"));
            cash3.setType(CashFlow.CREDIT);
            kSession.insert(cash3);

            CashFlow cash4 = new CashFlow();
            cash4.setAccountNo(2);
            cash4.setAmount(2111);
            cash4.setMvtDate(new SimpleDateFormat("yyyy-MM-dd").parse("2016-01-18"));
            cash4.setType(CashFlow.CREDIT);
            kSession.insert(cash4);
            
            AccountingPeriod period = new AccountingPeriod();
            period.setStartDate(new SimpleDateFormat("yyyy-MM-dd").parse("2016-01-01"));
            period.setEndDate(new SimpleDateFormat("yyyy-MM-dd").parse("2016-03-31"));
            kSession.insert(period);
            
            kSession.fireAllRules();
            //a.getBalance() MUST BE EQUAL TO 500


Notably, cash3 is out of the period and is not considered, as well as cash4 that is for account no. 2.





